<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>常用的API</title>
</head>

<body>
  <!-- 
  细讲下forEach() 与 map()的区别：
    map()会分配内存空间存储新数组并返回，forEach()不会返回数据但可以改变原数组。
 -->
</body>
<script>
  "use strict"; {
    let arr = ["slice", "splice", "split", "substring", "substr", "push", "pop", "shift", "unshift", "concat", "replace", "filter", "map", "foreach", "some", "every", "reduce", "reduceRight", "find", "findIndex", "findLastIndex", "indexOf", "lastIndexOf", "padStart", "padEnd", "repeat", "replaceAll", "includes", "startswith", "endswith", "decodeURIComponent", "encodeURIComponent", "JSON.stringify", "JSON.parse", "Number.NaN", "Number.isInteger", "Number.parseInt", "Number.parseFloat", "Number.EPSILON", "Number.isSafeInteger", "Array.from", "Array.of", "fill", "flat", "flatMap", "fromEntries", "entries", "in", "join", "toString", "Object.is", "Object.assign", "match", "matchAll", "exec", "test", "sort", "reverse", "lowerCase", "upperCase", "eval", "hasOwnProperty", "hasOwn", "getOwnPropertyNames", "defineProperties", "defineProperty", "getOwnPropertyDescriptor", "delete", "typeof", "instanceof", "~~", "Boolean", "Array.isArray", "isNaN", "Number.isNaN", "isFinite", "toFixed", "Reflect.ownKeys", "toLocaleString", "new Date().valueOf()", "Math.sign", "Math.min", "Object.setPrototypeOf", "trim", "structuredClone", "groupBy", "groupByToMap", "crypto.randomUUID()", "URLSearchParams()"];
  }; {
    // 组合函数的实现(每个函数必须要有返回值才行)
    const compose = (...funcs) => {
      return (x) => {
        return funcs.reduce((arg, fn) => {
          return fn(arg);
        }, x);
      };
    };
    let a = (n) => {
      return n + 1;
    };
    let b = (n) => {
      return n * 2;
    };
    let c = (n) => {
      return n + 2;
    };
    console.log(compose(a, b, c)(1));
  }; {
    // Infinity可以无限的展开多层结构
    let arr2 = [1, 2, [3, 4, [5]]].flat(Infinity);
    console.table(arr2);
  }; {
    let user = {
      name: "cz",
      hobby: ["打球", "跑步", "健身"],
      parent: {
        mother: "yan",
        father: "chen"
      }
    }
    // 目前谷歌还没有支持这个api
    let user1 = structuredClone(user)
  }
</script>
<!-- 
  forEach 和 map 方法的主要区别是 
    map() 方法会返回一个新的数组，而 forEach() 方法返回 undefined。
    那么这两个方法的使用该如何选择呢？
    如果你想基于原始数组得到一个新的数组，而不想改变原始数组，则选择使用 map() 方法，如果你只是在原数组上做迭代使用，不需要获得新的数组结果，可以选择 forEach。
    注意，这两个方法都一定会遍历数组中每个元素，除了抛出异常以外，没有办法中止或跳出循环遍历，如果你需要中止或跳出循环，则需要选择普通循环（while、do-while、for） 或 for...in、for...of 循环来实现。
 -->
<!-- 
  将所有的空格或．除去了
  replace(/\s/g,"");
 -->
<!-- 
fromEntries的使用
  通过 Object.fromEntries， 可以将 Map 转化为 Object:
    const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
    const obj = Object.fromEntries(map);
    console.log(obj); // { foo: "bar", baz: 42 }

  通过 Object.fromEntries， 可以将 Array 转化为 Object:
    const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
    const obj = Object.fromEntries(arr);
    console.log(obj); // { 0: "a", 1: "b", 2: "c" }
 -->
<!-- 
  使用repeat的重复输出多个/t
    let num = 10
    let i = ["好的", "看到", "你自大"].join(`,\n${"\t".repeat(num)}`)
    console.log(i)
 -->
<!-- 
  Number.isNaN与isNaN最的区别是，Number.isNaN不存在类型转换的行为。
  console.log(isNaN('测试')) //true
  console.log(Number.isNaN('测试')) //false
  
  isNaN会通过Number方法，试图将字符串"测试"转换成Number类型，但转换失败了，因为 Number('测试') 的结果为NaN ，所以最后返回true。
  而Number.isNaN方法，只是严格的判断传入的参数是否全等于NaN( '测试' === NaN) ，字符串当然不全等于NaN啦，所以输出false。
 -->

<!-- 
  根据换行或回车或空格进行识别
  let str = `上海市嘉定区希望路1333弄是啊我庭12号楼1203 王五
              13856385953`
  let arr = str.split(/[(\r\n)\r\n\s]+/)
  除去非中文数字字母
  str = str.split(/[^\u4e00-\u9fa5a-zA-Z0-9]+/g).filter(v=> v)
  -->

<!-- 
    判断多组字符串
    /Mobi|Android|iPhone/i.test()
    严格匹配
    /^(Mobi|Android|iPhone)$/i.test()
   -->

<!-- 
  Number.isNaN和isNaN的区别
   可能有一些童鞋会认为 isNaN直译为“是不是 NaN”，其本意不是，isNaN本意是通过Number方法把参数转换成数字类型，如若转换成功，则返回false，反之返回true，它只是判断参数是否能转成数字，不能用来判断是否严格等于NaN。，如果要判断某个值是否严格等于NaN不能用这个方法。ES6提供了Number.isNaN方法用来判断一个值是否严格等于NaN，它会首先判断传入的值是否为数字类型，如不是，直接返回false
-->

<!-- 
  hasOwn
  由于前面的几种方式都不优雅，ES2022有一个新的提议：Object.hasOwn
  如果指定的对象具有指定的属性作为其自己的属性，则 Object.hasOwn() 静态方法返回 true。
  如果属性被继承或不存在，则该方法返回 false。
 -->

</html>